Skip to content

Chore/typing#5

Merged
TonyPythoneer merged 9 commits into
developfrom
chore/typing
May 16, 2026
Merged

Chore/typing#5
TonyPythoneer merged 9 commits into
developfrom
chore/typing

Conversation

@TonyPythoneer

Copy link
Copy Markdown
Owner

No description provided.

TonyPythoneer and others added 9 commits May 16, 2026 07:18
Enable flake8-annotations (ANN) in ruff with ANN401 active so Any is
rejected. Add per-file ignores for tests/migrations/manage.py/conftest.

Annotate 32 previously untyped sites:
- decorators: PEP 695 ParamSpec on login_required_json to preserve
  wrapped view signatures end-to-end
- management commands: handle(*args: object, **options: object) -> None;
  s3 cached_property typed as S3Client (TYPE_CHECKING)
- storage: 3 __init__ return None
- tasks: generate_thumbnail self: Task (Celery bind=True)
- views: 5 HTML views -> HttpResponse
- models: _fmt_ts(dt: datetime | None)
Drop per-file ignores for manage.py, conftest.py, and tests/. Keep
migrations ignored — Django regenerates them via makemigrations and
would overwrite annotations.

- manage.py: main() -> None
- conftest.py: fixtures typed with Client, User, tuple[Client, User]
- factories.py: post_generation password method fully typed
- tests/: 38 test methods get -> None; fixtures typed via
  DjangoAssertNumQueries and Iterator[None] for yielding mock_s3
Collapse 6 duplicated test methods into 3 parametrized ones using
@pytest.mark.parametrize with named ids:

- test_login: matrix over (password, expected_status)
- test_create (images): matrix over (payload, expected_status)
- test_delete (images): matrix over (owned, expected_status, image_remains)
- test_create_task: matrix over (payload_kind, expected_status, task_created)
- test_get_task: matrix over (owned, expected_status)

18 test methods → 12 methods producing 17 cases. Tests with distinct
assertion shapes (cancel_task, list_query_count_constant, unauthenticated)
stay separate. ids=[...] keeps failure messages readable.
factory-boy class calls return the factory class to type checkers,
breaking IDE attribute resolution on returned model fields. Wrap
each factory in a helper that asserts the model return type via
typing.cast, restoring IDE/pyrefly visibility on .id, .latest_task,
refresh_from_db, etc. Pyrefly errors across tests drop from 40 to 8.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Promote generate_thumbnail max_retries to a module-level constant so
  tests reference the int directly instead of celery's untyped Task attr.
- Wrap celery .apply call in a Callable cast (stubs misreport it as list).
- factories.UserFactory.password: cast self to User (factory-boy injects
  the instance at runtime; pyrefly enforces LSP on self annotations).
- test_models: null-check latest_task() before .id access.
- pyrefly.toml: drop tests/ and management/ excludes; add manage.py.

Result: 0 pyrefly errors across the full project (was 40 with tests
included), no new type:ignore lines.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
DELETE /api/tasks/<id>/ let any owner revoke a running Celery task.
Task lifecycle should be controlled internally (admin/management), not
exposed to end users — removing the verb closes that surface.

tasks_detail now accepts GET only; AsyncResult import and the
test_cancel_task case are dropped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- test_tasks: split test_status_outcomes into test_direct_call (success
  and invalid_image) and test_resilient_to_download_failure (retry
  outcomes). Each method is now straight-line with no branching; the
  parametrize matrices align with their actual call mode.
- test_views_html: hoist URL names into class-level *_viewname
  attributes, matching the convention already used in test_api.py.
- test_smoke: rename infra-check helpers so each name announces the
  stack layer it covers (async worker, storage, observability) and
  drop the redundant docstrings. Add Jaeger query retry loop so the
  trace assertion no longer relies on a single fixed sleep.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wire a TracerProvider + OTLP gRPC exporter and RequestsInstrumentor in
the smoke test process so outbound HTTP calls inject traceparent and
emit client spans. Web/worker spans become children under a single
trace, enabling end-to-end visibility in Jaeger.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move Jaeger HTTP polling, response schemas, and helpers into a single
test-only module (images/tests/jaeger.py) with a JaegerClient singleton
mirroring the storage.py pattern. Response shapes are typed via
TypedDict, with a shared KeyedValue covering process/span/log fields
and NotRequired warnings to reflect Jaeger's optional payloads.

Switch smoke process to SimpleSpanProcessor so spans export
synchronously on end, removing the need for force_flush() before the
events assertion. The smoke root span now runs inline in the test
method via tracer.start_as_current_span, with trace_id read from the
span context. The trace is verified in two passes: service presence
inside the active span, then events on the root span after it ends.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@TonyPythoneer
TonyPythoneer merged commit 47d3d2e into develop May 16, 2026
3 checks passed
@TonyPythoneer
TonyPythoneer deleted the chore/typing branch May 16, 2026 11:34
@TonyPythoneer
TonyPythoneer restored the chore/typing branch May 16, 2026 11:34
@TonyPythoneer
TonyPythoneer deleted the chore/typing branch May 16, 2026 12:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant